﻿Imports System.Runtime.CompilerServices
Imports CookComputing.XmlRpc
Imports System.Globalization
Imports System.Diagnostics.Contracts

Namespace Extensions
    Module RpcExtensions

        ''' <summary>
        ''' Get value from XmlRpcStruct for the desidered key. If the key not exists or item have a different type, return default value.
        ''' </summary>
        ''' <typeparam name="T"></typeparam>	
        ''' <param name="xmlStruct">The XML struct.</param>
        ''' <param name="key">The key.</param>
        ''' <param name="default">The default.</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        <Extension()>
        Public Function GetValueOrDefault(Of T)(xmlStruct As XmlRpcStruct, key As String, [default] As T) As T
            Contract.Requires(Of NullReferenceException)(xmlStruct IsNot Nothing, "xmlStruct must be not null")
            Contract.Requires(Of ArgumentException)(Not String.IsNullOrEmpty(key), "key must be not null")
            If xmlStruct.ContainsKey(key) Then
                Try
                    Return CType(xmlStruct.Item(key), T)
                Catch ex As Exception
                    Return [default]
                End Try
            Else
                Return [default]
            End If
        End Function

        <Extension()>
        Public Function GetDouble(xmlStruct As XmlRpcStruct, key As String, [default] As Double) As Double
            Contract.Requires(Of NullReferenceException)(xmlStruct IsNot Nothing, "xmlStruct must be not null")
            Contract.Requires(Of ArgumentException)(Not String.IsNullOrEmpty(key), "key must be not null")
            Dim retVal As Double = [default]
            If xmlStruct.ContainsKey(key) Then
                Dim fi = New NumberFormatInfo()
                fi.NumberDecimalSeparator = "."
                If xmlStruct.Item(key) IsNot Nothing Then
                    retVal = Convert.ToDouble(xmlStruct.Item(key))
                Else
                    retVal = [default]
                End If
            End If
            Return retVal
        End Function

        <Extension()>
        Public Function GetDouble(xmlStruct As XmlRpcStruct, key As String, [default] As Double, formatProvider As IFormatProvider) As Double
            Contract.Requires(Of NullReferenceException)(xmlStruct IsNot Nothing, "xmlStruct must be not null")
            Contract.Requires(Of ArgumentException)(Not String.IsNullOrEmpty(key), "key must be not null")
            Contract.Requires(Of ArgumentException)(formatProvider IsNot Nothing, "formatProvider must be not null")
            Dim retVal As Double = [default]
            If xmlStruct.ContainsKey(key) Then
                Dim fi = New NumberFormatInfo()
                fi.NumberDecimalSeparator = "."
                If xmlStruct.Item(key) IsNot Nothing Then
                    retVal = Convert.ToDouble(xmlStruct.Item(key), formatProvider)
                Else
                    retVal = [default]
                End If
            End If
            Return retVal
        End Function

        <Extension()>
        Public Function GetNullableDouble(xmlStruct As XmlRpcStruct, key As String, [default] As Double?) As Double?
            Contract.Requires(Of NullReferenceException)(xmlStruct IsNot Nothing, "xmlStruct must be not null")
            Contract.Requires(Of ArgumentException)(Not String.IsNullOrEmpty(key), "key must be not null")
            Dim retVal As Double? = [default]
            If xmlStruct.ContainsKey(key) Then
                Dim fi = New NumberFormatInfo()
                fi.NumberDecimalSeparator = "."
                If xmlStruct.Item(key) IsNot Nothing Then
                    retVal = Convert.ToDouble(xmlStruct.Item(key))
                Else
                    retVal = [default]
                End If
            End If
            Return retVal
        End Function

        <Extension()>
        Public Function GetNullableDouble(xmlStruct As XmlRpcStruct, key As String, [default] As Double?, formatProvider As IFormatProvider) As Double?
            Contract.Requires(Of NullReferenceException)(xmlStruct IsNot Nothing, "xmlStruct must be not null")
            Contract.Requires(Of ArgumentException)(Not String.IsNullOrEmpty(key), "key must be not null")
            Contract.Requires(Of ArgumentException)(formatProvider IsNot Nothing, "formatProvider must be not null")
            Dim retVal As Double? = [default]
            If xmlStruct.ContainsKey(key) Then
                Dim fi = New NumberFormatInfo()
                fi.NumberDecimalSeparator = "."
                If xmlStruct.Item(key) IsNot Nothing Then
                    retVal = Convert.ToDouble(xmlStruct.Item(key), formatProvider)
                Else
                    retVal = [default]
                End If
            End If
            Return retVal
        End Function

        <Extension()>
        Public Function GetDateTime(xmlStruct As XmlRpcStruct, key As String, [default] As DateTime) As DateTime
            Contract.Requires(Of NullReferenceException)(xmlStruct IsNot Nothing, "xmlStruct must be not null")
            Contract.Requires(Of ArgumentException)(Not String.IsNullOrEmpty(key), "key must be not null")
            Dim retVal As DateTime = [default]
            If xmlStruct.ContainsKey(key) Then
                Dim myDTFI = New DateTimeFormatInfo()
                myDTFI.ShortDatePattern = "yyyy-MM-dd HH:mm:ss"
                myDTFI.LongDatePattern = "yyyy-MM-dd HH:mm:ss"
                If Not DateTime.TryParse(xmlStruct.Item(key).ToString(), myDTFI, DateTimeStyles.None, retVal) Then
                    retVal = [default]
                End If
            End If
            Return retVal
        End Function

    End Module
End Namespace